#include "t0022-0.h"
#include "cui.h"

#define MODNAME             "[CWIN]"
extern struct cui_widget_operations __window_ops;

int cui_window_parse(cJSON *root, struct cui_widget_st* widget)
{
    int retval = -1;
    cJSON *node, *widgetlist, *nodewidget;
    ERRSYS_INFOPRINT("### parsing WINDOW ...\n");

    /* 先解析layout */
    ERRSYS_INFOPRINT("### cui_layoutgrouplist_parse 1 widget %p...\n", widget);
    ERRSYS_INFOPRINT("### cui_layoutgrouplist_parse 1 cscr %p...\n", widget->cscr);
    cui_layoutgrouplist_parse(root, widget->cscr);
    ERRSYS_INFOPRINT("### cui_layoutgrouplist_parse 2 ...\n");

    retval = cui_attributes_parse(root, widget, &__window_ops, NULL);
    if (retval == -1) {
        goto err;
    }
    cui_dump_layout(&widget->cscr->layoutgrouplist);
    
    cui_dump_widget_hierarchy(widget);


    widgetlist = cJSON_GetObjectItem(root, CUI_CONFIELD_WIDGETLIST);
    if (cJSON_ValidArray(widgetlist)) {
        int i;
        int nwidgets = cJSON_GetArraySize(widgetlist);
        struct cui_widget_st *subwidget = NULL;
        struct cui_widget_st *widgetprev = NULL;
        ERRSYS_INFOPRINT("WINDOWS parse, total widgets: %d\n", nwidgets);
        ERRSYS_INFOPRINT("parsing subwidgets BEGIN ...\n");
        for (i = 0;i < nwidgets;i ++) {
            nodewidget = cJSON_GetArrayItem(widgetlist, i);
            // ERRSYS_INFOPRINT("parsing node %s\n", cJSON_Print(nodewidget));
            node = cJSON_GetObjectItem(nodewidget, CUI_CONFIELD_ENABLE);
            if(cJSON_ValidNumber(node) == 0 || node->valueint != CUI_CONFIG_FIELDVALUE_TRUE){
                continue;
            }
            node = cui_guess_widgetnode(nodewidget);
            if (node != NULL) {
                struct cui_widget_operations *widgetops = get_widget_operation(node->string);
                if (widgetops == NULL) {
                    ERRSYS_INFOPRINT("no operation found for widget %s\n", node->string);
                    continue;
                }
                // else {
                //     ERRSYS_INFOPRINT("[%s]operation found\n", node->string);
                // }
                subwidget = cui_new_widget(widget->id, widget->cscr, widgetops, widget, widgetprev);

                retval = widgetops->parse(node, subwidget);

                if(retval == 0){
                    widgetprev = subwidget;
                    list_add_tail(&subwidget->node, &widget->widgetlist);
                    ERRSYS_INFOPRINT("\"%s\" is added to \"%s\"\n", subwidget->name, widget->name);
                }
                else {
                    cui_widget_destroy(subwidget);
                }
            }
        }
        ERRSYS_INFOPRINT("parsing subwidgets END ...\n");
    }
    retval = 0;
err:
    return retval;
}

int cui_window_create(struct cui_widget_st *widget)
{
    if (widget != NULL) {
        ERRSYS_INFOPRINT("[%s] created lines:%d cols:%d x:%d y:%d\n", widget->name,
        widget->lines, widget->cols, widget->beginx, widget->beginy);
        widget->win = newwin(widget->lines, widget->cols, widget->beginy, widget->beginx);
        cui_dump_widget(widget);
        if (widget->win != NULL) {
            return 0;
        }
    }
    return -1;
}

void cui_window_paint(struct cui_widget_st *widget)
{
    
    if (widget != NULL) {
        WINDOW *win = widget->win;
        int w, h, split_y;
        // struct cui_widget_border_st *border;
        /* 2 lines/cols included for the border frame */
        w = widget->cols;
        h = widget->lines;

        if (IS_WIDGET_BORDER(widget)) {
            ERRSYS_INFOPRINT("[%s] paint border cols:%d rows:%d\n", widget->name, w, h);
            box(win, 0, 0);
        }
#if 0
        /* draw 4 corners first */
        border = &widget->border;
        mvwaddch(win, y, x, border->tl);  // top-left corner
        mvwaddch(win, y, x + w - 1, border->tr);  // top-right corner
        mvwaddch(win, y + h - 1, x, border->bl);  // bottom-left corner
        mvwaddch(win, y + h - 1, x + w - 1, border->br);  // bottom-right corner
        /* draw 2 horizontal/vertical lines, skipped the start/stop corners */
        mvwhline(win, y, x + 1, border->ts, w - 2);   // top side
        mvwhline(win, y + h - 1, x + 1, border->bs, w - 2);   // bottom side
        mvwvline(win, y + 1, x, border->ls, h - 2);      // left side
        mvwvline(win, y + 1, x + w - 1, border->rs, h - 2);   // right side
#endif
        /* draw title */
        // cui_dump_widget(widget);
        if (IS_WIDGET_TITLE(widget)) {
            split_y = CUI_WIDGET_TITLESPLITTER_COLOFFSET;
            ERRSYS_INFOPRINT("[%s] paint title split line yoffset:%d xoffset:%d\n", widget->name, split_y, 0);
            mvwaddch(win, split_y, 0, ACS_LTEE);
            mvwhline(win, split_y, 1, ACS_HLINE, w - 2);
            mvwaddch(win, split_y, w - 1, ACS_RTEE);
            cui_print(win, split_y - 1, 1, w - 2, widget->title, WHTBLK, CUI_PRINT_ALIGNMENT_MIDDLE);
        }

        wrefresh(widget->win);
        // ERRSYS_INFOPRINT("[%s]%s cols:%d line:%d\n", widget->name, __func__, w, h);
    }
}

// free widget inside
void cui_window_destroy(struct cui_widget_st *widget)
{
    if (widget != NULL) {
        ERRSYS_INFOPRINT("destroy widget (%s)\n", widget->name);
        if (widget != NULL && widget->win != NULL) {
            // clean the terminal
            // wborder(cwin->win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
            // wrefresh(cwin->win);
            delwin(widget->win);
            widget->win = NULL;
            widget->widgetinstance = NULL;
            // free(widget);
        }
    }
    return;
}

int cui_window_keyevent(struct cui_widget_st* widget, int key)
{
    int handled = CUI_WIDGETEVENT_PROPAGATION;
    // ERRSYS_INFOPRINT("[%s] %s 1\n", widget->name, __func__);
    /* customized handler */
    if (widget->cb.keyevent != NULL) {
        handled = widget->cb.keyevent(widget, key);
        ERRSYS_INFOPRINT("[%s]%s KEY=%d retval %d\n", widget->name, __func__, key, handled);
    }
    // ERRSYS_INFOPRINT("[%s] %s 2\n", widget->name, __func__);
    if (handled == CUI_WIDGETEVENT_PROPAGATION) {
        switch (key) {
            case KEY_ESC:
                // ERRSYS_INFOPRINT("[%s] %s cui_screen_pop\n", widget->name, __func__);
                cui_screen_pop(widget->cscr);
                // ERRSYS_INFOPRINT("[%s] %s cui_refresh\n", widget->name, __func__);
                cui_refresh(widget->cscr, -1);
                // ERRSYS_INFOPRINT("[%s] %s cui_refresh after\n", widget->name, __func__);
                handled = CUI_WIDGETEVENT_HANDLED;
                break;
        }
    }
    // ERRSYS_INFOPRINT("[%s] %s 3\n", widget->name, __func__);

    return handled;
}

struct cui_widget_operations __window_ops = {
    .name = "window",
    .parse = cui_window_parse,
    .create = cui_window_create,
    .destroy = cui_window_destroy,
    .paint = cui_window_paint,
    .keyevent = cui_window_keyevent,
};